package com.qk.management.aop;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.qk.common.util.CurrentUserContextHolders;
import com.qk.entity.OperateLog;
import com.qk.management.mapper.OperateLogMapper;
import com.qk.vo.portal.PortalVO;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

//日志记录切面
@Component
@Aspect
@Slf4j
public class LogRecordAspect {
    @Autowired
    private OperateLogMapper operateLogMapper;
    @Autowired//创建一个spring data redis对象操作
    private StringRedisTemplate springRedisTemlate;
    private static final String CACHE_PORTAL_KEY_PREFIX = "qk:portal:";


    @Pointcut("@annotation(com.qk.management.aop.annotation.LogAnno)")
    public void pt() {}

    @Around("pt()")
    public Object log(ProceedingJoinPoint pjp){//做业务，不能抛异常!!!
        //前逻辑
        //System.out.println("开始记录日志...");

        //定义目标方法的返回值
        Object returnValue = null;
        try {
            long startTime = System.currentTimeMillis();
            //执行切点方法
            returnValue = pjp.proceed();

            long endTime = System.currentTimeMillis();

            //获取操作人id
            Integer userId = CurrentUserContextHolders.get();
            //获取参数
            Object[] args = pjp.getArgs();
            String jsonStr = JSONUtil.toJsonStr(args);
            //构造一个OperateLog对象
            OperateLog operateLog = OperateLog.builder()
                    .costTime(endTime-startTime)//接口执行时间
                    .methodName(pjp.getSignature().getName())
                    .operateUserId(userId)
                    .operateTime(LocalDateTime.now())
                    .className(pjp.getTarget().getClass().getName())
                    .methodName(pjp.getSignature().getName())
                    .methodParams(jsonStr)
                    .returnValue(JSONUtil.toJsonStr(returnValue))
                    .build();

            //调用mapper
            operateLogMapper.insert(operateLog);
        } catch (Throwable e) {
            //记录日志成功与否绝对不能影响正常业务执行!!!
            //returnValue= Result.error("操作失败");
            log.error("日志记录操作失败：{}", e.getMessage());
        }

        //后逻辑
        //System.out.println("结束记录日志...");

        return returnValue;
    }



    @Pointcut("execution(* com.qk.management.service.impl.ReportOverviewServiceImpl.getReportOverview())")
    public void pt2() {}
    @Around("pt2()")
    public Object log2(ProceedingJoinPoint pjp){
        Object returnValue = null;
        try {
            //定义缓存key
            String cacheKey = CACHE_PORTAL_KEY_PREFIX + "reportOverview";

            //先查询缓存(看下是否缓存命中)
            String jsonStrFromRedis = null;
            try {
                jsonStrFromRedis = springRedisTemlate.opsForValue().get(cacheKey);
                if (ObjectUtil.isNotEmpty(jsonStrFromRedis)) {
                    //如果缓存命中直接返回
                    PortalVO portalVO = JSONUtil.toBean(jsonStrFromRedis, PortalVO.class);
                    return portalVO;
                }
            } catch (Exception e) {
                log.error("-----查询缓存失败-----", e);
            }

            returnValue = pjp.proceed();

        } catch (Throwable e) {
            log.error("缓存操作失败：{}", e.getMessage());
        }

        return returnValue;
    }
}
